using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Reflection;
using System.Text;
using Terra.Core.Configuration;
using Terra.Core.Configuration.Options;
using Terra.Core.Constants;
using Terra.Core.Infrastructure.Security;
using Terra.Core.Security.Options;
using Terra.Core.Security.Services;
using Terra.Core.Security.Permissions;
using Terra.Data.Context;
using Terra.Data.Extensions;
using Terra.Service.Identity.Implementations;
using Terra.Service.Identity.Interfaces;
using System.Security.Claims;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.AspNetCore.Authorization;
using AutoMapper;
using Terra.Core.Common.ErrorCodes.Providers;
using Terra.Core.Common.ApiResponse;
using Terra.Core.Common.ErrorCodes.Extensions;
using Terra.Service.Common.Extensions;
using Terra.Core.Security;
using Terra.WebApi.Filters;
using Terra.Service.Common.Infrastructure.ExceptionHandling;
using Terra.Core.Common.Filters;

var builder = WebApplication.CreateBuilder(args);

// 添加配置源
builder.Configuration
    .SetBasePath(builder.Environment.ContentRootPath)
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true)
    .AddEnvironmentVariables();

// 注册配置到服务容器
builder.Services.Configure<AppSettings>(builder.Configuration.GetSection("App"));
// 注入 AuthSettings 配置
builder.Services.Configure<AuthSettings>(builder.Configuration.GetSection("Auth"));

// 添加 HttpContextAccessor
builder.Services.AddHttpContextAccessor();

// 注册应用服务
builder.Services.AddApplicationServices(builder.Configuration);

// 添加JWT配置
builder.Services.Configure<JwtOptions>(builder.Configuration.GetSection("Auth:Jwt"));
builder.Services.AddScoped<IJwtService, JwtService>();

// 配置日志
builder.Logging.AddConsole();
builder.Logging.SetMinimumLevel(LogLevel.Debug);
builder.Logging.AddDebug();

// 添加认证日志
builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    var jwtOptions = builder.Configuration.GetSection("Auth:Jwt").Get<JwtOptions>();
    if (string.IsNullOrEmpty(jwtOptions?.SecretKey))
    {
        throw new InvalidOperationException("JWT SecretKey is not configured.");
    }

    var keyBytes = Encoding.UTF8.GetBytes(jwtOptions.SecretKey);
    if (keyBytes.Length < 32)
    {
        throw new InvalidOperationException("JWT SecretKey must be at least 32 characters long.");
    }

    options.SaveToken = true;
    options.RequireHttpsMetadata = false; // 开发环境暂时关闭HTTPS要求
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = jwtOptions.Issuer,
        ValidAudience = jwtOptions.Audience,
        IssuerSigningKey = new SymmetricSecurityKey(keyBytes),
        ClockSkew = TimeSpan.Zero
    };

    // 添加详细的事件处理
    options.Events = new JwtBearerEvents
    {
        OnAuthenticationFailed = context =>
        {
            var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Program>>();
            logger.LogError("Authentication failed: {Exception}", context.Exception);

            if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
            {
                context.Response.Headers.Append("Token-Expired", "true");
                logger.LogWarning("Token has expired");
            }
            return Task.CompletedTask;
        },
        OnMessageReceived = context =>
        {
            var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Program>>();
            var token = context.Request.Headers["Authorization"].ToString();
            logger.LogInformation("Received token: {Token}", token);
            return Task.CompletedTask;
        },
        OnTokenValidated = context =>
        {
            var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Program>>();
            var identity = context.Principal?.Identity as ClaimsIdentity;

            if (identity?.Claims != null)
            {
                logger.LogInformation("Token claims: {Claims}",
                    string.Join(", ", identity.Claims.Select(c => $"{c.Type}: {c.Value}")));
            }
            return Task.CompletedTask;
        },
        OnChallenge = context =>
        {
            var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Program>>();
            logger.LogWarning("Authorization challenge: {Error}, {ErrorDescription}",
                context.Error, context.ErrorDescription);

            context.HandleResponse();
            context.Response.StatusCode = 401;
            context.Response.ContentType = "application/json";
            var result = System.Text.Json.JsonSerializer.Serialize(new
            {
                error = "Unauthorized",
                message = "You are not authorized to access this resource",
                details = $"Error: {context.Error}, Description: {context.ErrorDescription}"
            });
            return context.Response.WriteAsync(result);
        }
    };
});

// 添加授权策略
builder.Services.AddAuthorization(options =>
{
    // 默认策略
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
        .Build();

    // Admin策略
    options.AddPolicy("AdminPolicy", policy =>
        policy.RequireAuthenticatedUser()
            .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
            .RequireClaim(ClaimTypes.Role, "Administrator")
    );

    // API访问策略
    options.AddPolicy("ApiScope", policy =>
        policy.RequireAuthenticatedUser()
            .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
            .RequireClaim("scope", "api1")
    );

    // 添加权限策略
    options.AddPolicy(SecurityConstants.PermissionPolicyName, policy =>
        policy.Requirements.Add(new PermissionRequirement())
    );
});

// 注册权限处理器
builder.Services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>();

// 在 builder.Services 配置部分添加（添加在 AddControllers 之前）
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowWebApp", builder =>
    {
        builder.WithOrigins("http://localhost:5777") // 前端应用的地址
               .AllowAnyMethod()
               .AllowAnyHeader()
               .AllowCredentials();
    });
});

// 在开发环境中添加详细的错误信息
builder.Services.AddControllers(options =>
{
    // 添加全局模型验证过滤器
    options.Filters.Add<ValidationFilter>();
})
.ConfigureApiBehaviorOptions(options =>
{
    // 禁用默认的模型验证响应
    options.SuppressModelStateInvalidFilter = true;
});
builder.Services.AddEndpointsApiExplorer();

// 配置 Swagger
builder.Services.AddSwaggerGen(options =>
{
    // 添加后台管理接口文档
    options.SwaggerDoc("v1-admin", new OpenApiInfo
    {
        Title = "Terra Admin API",
        Version = "v1",
        Description = "Terra 平台后台管理接口文档",
        Contact = new OpenApiContact
        {
            Name = "Terra Team",
            Email = "support@terra.com"
        }
    });

    // 添加PC端接口文档
    options.SwaggerDoc("v1-client", new OpenApiInfo
    {
        Title = "Terra Client API",
        Version = "v1",
        Description = "Terra 平台PC端接口文档",
        Contact = new OpenApiContact
        {
            Name = "Terra Team",
            Email = "support@terra.com"
        }
    });

    // 添加移动端接口文档
    options.SwaggerDoc("v1-mobile", new OpenApiInfo
    {
        Title = "Terra Mobile API",
        Version = "v1",
        Description = "Terra 平台移动端接口文档",
        Contact = new OpenApiContact
        {
            Name = "Terra Team",
            Email = "support@terra.com"
        }
    });

    // 添加 Bearer 认证配置
    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer"
    });

    // 使用自定义的安全需求过滤器
    options.OperationFilter<SecurityRequirementsOperationFilter>();

    // 添加 XML 注释文档
    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    if (File.Exists(xmlPath))
    {
        options.IncludeXmlComments(xmlPath);
    }
    // 添加 Data 层的 XML 文档
    var dataXmlFile = "Terra.Data.xml";
    var dataXmlPath = Path.Combine(AppContext.BaseDirectory, dataXmlFile);
    if (File.Exists(dataXmlPath))
    {
        options.IncludeXmlComments(dataXmlPath);
    }

    // 添加 Service 层的 XML 文档
    var serviceXmlFile = "Terra.Service.xml";
    var serviceXmlPath = Path.Combine(AppContext.BaseDirectory, serviceXmlFile);
    if (File.Exists(serviceXmlPath))
    {
        options.IncludeXmlComments(serviceXmlPath);
    }

    // 添加 Core 层的 XML 文档（如果需要）
    var coreXmlFile = "Terra.Core.xml";
    var coreXmlPath = Path.Combine(AppContext.BaseDirectory, coreXmlFile);
    if (File.Exists(coreXmlPath))
    {
        options.IncludeXmlComments(coreXmlPath);
    }
});

// 添加API版本控制
builder.Services.AddApiVersioning(options =>
{
    options.DefaultApiVersion = new ApiVersion(1, 0);
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.ReportApiVersions = true;
});

builder.Services.AddVersionedApiExplorer(options =>
{
    options.GroupNameFormat = "'v'VVV";
    options.SubstituteApiVersionInUrl = true;
});

// 添加项目配置
builder.Services.Configure<ProjectSettings>(builder.Configuration.GetSection("ProjectSettings"));
builder.Services.AddSingleton(sp => sp.GetRequiredService<IOptions<ProjectSettings>>().Value);

// 添加错误码服务
builder.Services.AddErrorCodes(builder.Configuration);

// 添加 AutoMapper
builder.Services.AddAutoMapper(typeof(Terra.Service.Common.Mappers.AutoMapperProfile).Assembly);

// 添加数据库上下文
builder.Services.AddDbContext<TerraDbContext>(options =>
{
    var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
    if (string.IsNullOrEmpty(connectionString))
    {
        throw new InvalidOperationException("Database connection string 'DefaultConnection' is not configured.");
    }

    options.UseSqlServer(connectionString, sqlOptions =>
    {
        sqlOptions.EnableRetryOnFailure(
            maxRetryCount: builder.Configuration.GetValue<int>("Database:MaxRetryCount", 3),
            maxRetryDelay: TimeSpan.FromSeconds(builder.Configuration.GetValue<int>("Database:RetryInterval", 5)),
            errorNumbersToAdd: null);

        sqlOptions.CommandTimeout(builder.Configuration.GetValue<int>("Database:CommandTimeout", 30));
    });

    if (builder.Environment.IsDevelopment())
    {
        options.EnableSensitiveDataLogging();
        options.EnableDetailedErrors();
    }
});

// 添加数据访问服务
builder.Services.AddDataAccess();

// 添加身份认证服务
builder.Services.AddScoped<IAuthService, AuthService>();

// 初始化项目常量
ProjectConstants.Initialize(builder.Configuration);

var app = builder.Build();

// 初始化 ApiResponse 的 ErrorCodeProvider
var errorCodeProvider = app.Services.GetRequiredService<IErrorCodeProvider>();
ApiResponse.Initialize(errorCodeProvider);

// 注册全局异常处理中间件（放在最前面以捕获所有异常）
app.UseGlobalExceptionHandling();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1-admin/swagger.json", "后台管理接口 V1");
        c.SwaggerEndpoint("/swagger/v1-client/swagger.json", "PC端接口 V1");
        c.SwaggerEndpoint("/swagger/v1-mobile/swagger.json", "移动端接口 V1");
        c.RoutePrefix = "swagger";

        // 设置Swagger UI主题
        c.InjectStylesheet("/swagger-ui/custom.css");

        // 展开/折叠标签
        c.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.None);

        // 显示请求持续时间
        c.DisplayRequestDuration();

        // 启用过滤器
        c.EnableFilter();

        // 启用深层链接
        c.EnableDeepLinking();

        // 显示操作ID
        c.DisplayOperationId();

        // 配置OAuth持久化
        c.ConfigObject.AdditionalItems["persistAuthorization"] = true;

        // 默认的请求头
        c.ConfigObject.AdditionalItems["defaultModelRendering"] = "model";

        // 配置JSON编辑器
        c.ConfigObject.AdditionalItems["defaultModelExpandDepth"] = 3;
        c.ConfigObject.AdditionalItems["showCommonExtensions"] = true;
    });
}

app.UseHttpsRedirection();

// 启用路由中间件
app.UseRouting();

// 在中间件管道中，UseRouting 之后，UseAuthentication 之前添加
app.UseCors("AllowWebApp");

// 添加认证和授权中间件
app.UseAuthentication();
app.UseAuthorization();

// 添加Areas路由支持
app.MapControllerRoute(
    name: "areas",
    pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

// 启用控制器路由
app.MapControllers();

var summaries = new[]
    {
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
    {
        var forecast = Enumerable.Range(1, 5).Select(index =>
            new WeatherForecast
            (
                DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                Random.Shared.Next(-20, 55),
                summaries[Random.Shared.Next(summaries.Length)]
            ))
            .ToArray();
        return forecast;
    })
    .WithName("GetWeatherForecast")
    .WithOpenApi();

// 添加测试异常端点
app.MapGet("/test-error", () =>
{
    throw new Exception("这是一个测试异常，用于验证全局异常处理中间件");
})
.WithName("TestError")
.WithOpenApi();

app.Run();

record WeatherForecast(DateOnly Date, int TemperatureC, string Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
